package beancopy.orika;

import beancopy.dto.OriginClass;
import beancopy.dto.OriginOrder;
import beancopy.dto.TargetClass;
import beancopy.dto.TargetOrder;
import beancopy.util.Demo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import lombok.SneakyThrows;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName OrikaDemo
 * @Description
 * @Author ihcy
 * @Date 2020/1/13 20:53
 * @Version 1.0
 **/
public class OrikaDemo {

    public static void main(String[] args) {
//        testSameNameField();
//        testList();
//        testDiffField();
        testClass();
    }

    private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    /**
     * 1. 属性名称映射  同字段类型可以，不同类型默认不可
     */
    @SneakyThrows
    public static void testSameNameField() {
        MapperFacade orderFacade = mapperFactory.getMapperFacade();
        List<OriginOrder> originOrders = Demo.getOriginOrders();

        //默认情况下，orika只会把两个类，名称相同的两个属性做相应的拷贝
        OriginOrder originOrder = originOrders.get(0);
        TargetOrder targetOrder = orderFacade.map(originOrder, TargetOrder.class);
        System.out.println(test(targetOrder, originOrder));

        // 字段属性名相同，类型不匹配 ok (类型会自动转换)。String->Date 出错 ; Date->String Tue Jan 14 14:09:15 CST 2020
        originOrder.setStringToInteger("1");
        // originOrder.setStringToDate("2019-05-60");
        originOrder.setDateToString(new Date());
        originOrder.setIntegerToString(1);
        targetOrder = orderFacade.map(originOrder, TargetOrder.class);
        System.out.println(targetOrder.getStringToInteger());
        System.out.println(targetOrder.getDateToString());
        System.out.println(targetOrder.getIntegerToString());
        System.out.println(test(targetOrder, originOrder));

    }

    /**
     * 4. ✔ List 递归 内嵌Bean(内嵌Bean类型名称一致)
     */
    public static void testList() {
        MapperFacade orderFacade = mapperFactory.getMapperFacade();
        List<OriginOrder> originOrders = Demo.getOriginOrders();

        // 递归拷贝ok true
        List<TargetOrder> targetOrders = orderFacade.mapAsList(originOrders, TargetOrder.class);
        System.out.println(test(targetOrders, originOrders));
    }

    /**
     * 测试不同属性名，类型转换
     */
    public static void testDiffField() {
        mapperFactory.getConverterFactory().registerConverter("StringDate", new StringDateConverter());
        // 属性名不同，类型相同，可以匹配
        mapperFactory.classMap(OriginClass.Std.class, TargetClass.Student.class)
                .field("stdname", "name")
                .field("stdid", "id")
                .fieldMap("time", "time").converter("StringDate").add()
                .byDefault()
                .register();
        OriginClass.Std std = new OriginClass.Std("name", "1", "2020-01-01");
        TargetClass.Student student = mapperFactory.getMapperFacade().map(std, TargetClass.Student.class);
        System.out.println(student.getTime());
        System.out.println(test(std, student));
    }

    /**
     * 类型，字段名都不统一。
     */
    public static void testClass() {
        mapperFactory.getConverterFactory().registerConverter("StringDate", new StringDateConverter());
        mapperFactory.getConverterFactory().registerConverter("CodeEnumConvert", new CodeEnumConvert());
        mapperFactory.classMap(OriginClass.class, TargetClass.class)
                .field("classid", "id")
                .field("classname", "className")
                .fieldMap("date", "time").converter("StringDate").add()
                .field("num", "number")
                .field("stds", "students")
                .fieldMap("code", "codeEnum").converter("CodeEnumConvert").add()
                .field("tea", "teacher")
                .byDefault().register();

        // stu 匹配
        mapperFactory.classMap(OriginClass.Std.class, TargetClass.Student.class)
                .field("stdname", "name")
                .field("stdid", "id")
                .fieldMap("time", "time").converter("StringDate").add()
                .byDefault()
                .register();
        List<OriginClass> originClasses = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            OriginClass originClass = new OriginClass();
            originClass.setClassid("" + i);
            originClass.setClassname("name" + i);
            originClass.setDate("2020-01-01");
            originClass.setNum("" + (i * 5));
            originClass.setCode(i);
            originClass.setTea(new OriginClass.Tea("tea" + i, "" + i));
            List<OriginClass.Std> stds = new ArrayList<>();
            originClass.setStds(stds);
            for (int j = 0; j < 5; j++) {
                OriginClass.Std std = new OriginClass.Std("std" + i + j, "" + i + j, "2020-01-02");
                stds.add(std);
            }
            originClasses.add(originClass);
        }

        OriginClass originClass = originClasses.get(0);
        TargetClass targetClass = mapperFactory.getMapperFacade().map(originClass, TargetClass.class);
        test(originClass, targetClass);

        List<TargetClass> targetClasses = mapperFactory.getMapperFacade().mapAsList(originClasses, TargetClass.class);
        test(originClasses, targetClasses);

        targetClasses.get(0).setClassName("testname");
        targetClasses.get(0).getTeacher().setName("111");

    }

    private static <K, V> Boolean test(K k, V v) {
        String kJson = JSON.toJSONString(k, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.SortField);
        String vJson = JSON.toJSONString(v, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.SortField);
        System.out.println(kJson);
        System.out.println(vJson);
        return kJson.equals(vJson);
    }
}
